#ifndef __DEVICE_DEF_H__
#define __DEVICE_DEF_H__

#include <stdint.h>

// 设备返回值
typedef enum DEV_RET{
    DEV_OK = 0,             // 成功

    DEV_NULL,               // 空指针
    DEV_IS_OPEN,            // 设备已打开
    DEV_DESC_NULL,          // 描述为空
    DEV_CONTEXT_NULL,       // 上下文为空
    DEV_MALLOC_ERR,         // 内存分配错误

    DEV_TYPE_ERR,           // 类型错误

    DEV_ARG_NULL,           // 参数为空
    DEV_ARG_ERR,            // 参数错误

    DEV_DATA_NULL,          // 数据为空
    DEV_DATA_SIZE_ERR,      // 数据长度错误
    DEV_DATA_OVERFLOW,      // 数据溢出

    DEV_EVT_OVERFLOW,       // 事件溢出
    DEV_UNKNOWN_EVENT,      // 未知事件

    DEV_BUF_NULL,           // 缓冲区为空
    DEV_BUF_OVERFLOW,       // 缓冲区溢出

    DEV_IOCTL_NULL,         // ioctl命令为空
    DEV_UNKNOWN_IOCTL,      // 未知ioctl命令

    DEV_INTERFACE_NULL,     // 接口为空
    DEV_OPS_ERR,            // 接口操作错误

    DEV_LOCKED,             // 设备被锁定
    DEV_BUSY,               // 设备忙

}Dev_Ret_t;

// 定义IO状态
enum {
    IO_STATUS_LOW  = 0,    // 低电平
    IO_STATUS_HIGH = 1     // 高电平
};

// 定义事件状态
enum {
    EVENT_STATUS_UNSET = 0,    // 事件未发生
    EVENT_STATUS_SET   = 1     // 事件发生
};

// 设备最大事件位
#define MAX_EVENT_BITS 14
#if (MAX_EVENT_BITS + 2 > 16)
        #error "MAX_EVENT_BITS must be less than or equal to 16"
#endif

// 设备结构体
typedef struct Device{
    void*       pvContext;          // 设备上下文 
    uint8_t     u8Type;             // 设备类型
    uint8_t     u8Reserve;          // 预留位
    union {                         // 事件状态
        uint16_t u16Event;
        struct {
            uint16_t u16Event0:1;    // 事件位
            uint16_t u16Event1:1;    // 事件位
            uint16_t u16Event2:1;    // 事件位
            uint16_t u16Event3:1;    // 事件位
            uint16_t u16Event4:1;    // 事件位
            uint16_t u16Event5:1;    // 事件位
            uint16_t u16Event6:1;    // 事件位
            uint16_t u16Event7:1;    // 事件位
            uint16_t u16Event8:1;    // 事件位
            uint16_t u16Event9:1;    // 事件位
            uint16_t u16Event10:1;   // 事件位
            uint16_t u16Event11:1;   // 事件位
            uint16_t u16Event12:1;   // 事件位
            uint16_t u16Event13:1;   // 事件位
    
            uint16_t u16Lock:1;     // 锁定状态
            uint16_t u16Busy:1;     // 忙状态
        } bit;
    } stEvent;
}Device_t;

// 设备基类大小
#define DEV_SIZE sizeof(Device_t)

// 设备事件发生宏定义   
#define DEV_EMIT_EVENT(pstDevice, u8EvtBit) \
    pstDevice->stEvent.u16Event |= (1U << u8EvtBit) \

// 设备事件描述结构体
typedef struct DevEvtDesc {
    uint8_t     u8EvtBit;       // 事件位
    uint8_t     u8EvtState;     // 事件状态 @see EVENT_SET, EVENT_UNSET
    uint16_t    u16Reserve;     // 预留位
}DevEvtDesc_t;

// 设备事件描述大小
#define DEV_EVT_DESC_SIZE sizeof(DevEvtDesc_t)

// 设备描述结构体
typedef struct DevDesc {
    Device_t**  pstDevice;      // 设备指针
    void*       pvContext;      // 设备上下文 
    uint16_t    u16Size;        // 设备上下文大小
    uint8_t     u8Type;         // 设备类型
    uint8_t     u8Reserve;      // 预留位
}DevDesc_t;

// 设备描述大小
#define DEV_DESC_SIZE sizeof(DevDesc_t)

// 获取设备上下文指针
#define GET_CONTEXT(pstDevice, type) ((type*)pstDevice->pvContext)

// 检查设备锁定和繁忙状态
#define DEV_CHECK_STATUS(pstDevice) \
    if(1 == pstDevice->stEvent.bit.u16Lock) \
    { \
        return DEV_LOCKED; \
    } \
    \
    if(1 == pstDevice->stEvent.bit.u16Busy) \
    { \
        return DEV_BUSY; \
    }\

// 锁定设备
#define DEV_LOCKED(pstDevice) \
pstDevice->stEvent.bit.u16Lock = 1 \

// 解锁设备
#define DEV_UNLOCK(pstDevice) \
pstDevice->stEvent.bit.u16Lock = 0 \

// 设置设备忙状态
#define DEV_SET_BUSY(pstDevice) \
    pstDevice->stEvent.bit.u16Busy = 1 \

// 设置设备空闲状态
#define DEV_SET_IDLE(pstDevice) \
    pstDevice->stEvent.bit.u16Busy = 0 \

/* 声明一个设备的 context 类型 */
#define DEVICE_CONTEXT_DECLARE(name, hw_type, sw_type)  \
    typedef struct name \
    {   \
        hw_type HW;         \
        sw_type SW;         \
    } name##_t

// ioctl接口抛出宏定义
#define EXPORT_DEV_IOCTL(name) extern Dev_Ret_t dev_##name##_ioctl(Device_t *pstDevice, uint8_t u8Cmd, void *pvArg)

// 设备ioctl处理函数类型定义
typedef Dev_Ret_t (*pfn_ioctl_t)(Device_t *pstDevice, uint8_t u8Cmd, void *pvArg);

// 设备ioctl处理函数指针映射表
extern const pfn_ioctl_t g_stDevIoctlMap[];

#endif /* __DEVICE_DEF_H__ */
